<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React Antd App</title>
    <!-- <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script> -->
    <script src="js/ext/babel.min.js"></script>
    <script crossorigin src="js/ext/react.development.js"></script>
    <script crossorigin src="js/ext/react-dom.development.js"></script>
    <script src="js/ext/semi-ui.min.js"></script>
    <link rel="stylesheet" href="css/semi.css">
    <script src="js/ext/semi-icons.min.js"></script>
    <link rel="stylesheet" href="css/semi-icons.css">
    <script src="js/ext/semi-illustrations.min.js"></script>

    <link rel="stylesheet" href="./css/index.min.css">
    <script src="./js/api.js"></script>
</head>

<body>
    <div id="root"></div>
    <script type="text/babel">
        const { useState, useCallback, useEffect, useRef } = React;
        const { Input, Button, Toast, Icon, Form, Chat, Radio, Tabs, TabPane, Tooltip, Select, Card, Space } = SemiUI;
        console.log(userInfo, 'userInfo')

        const ChartDom = ({ agentList }) => {
            console.log(SemiUI); // 查看 Chat 是否存在

            const [activeAgentInfo, setActiveAgentInfo] = useState({ id: 1 });

            const handleOfAgentChange = (value) => {
                const selectedAgent = agentList.find((item) => item.id == value);
                if (selectedAgent) {
                    setActiveAgentInfo({ id: selectedAgent.id, name: selectedAgent.name });
                }
            };

            const getId = () => Math.random().toString(36).substr(2, 9);
            const [mode, setMode] = useState('bubble');
            const [align, setAlign] = useState('leftRight');
            const uploadProps = { action: 'https://api.semi.design/upload' }
            const defaultMessage = [
                {
                    role: 'assistant',
                    id: '1',
                    createAt: 1715676751919,
                    content: "你好，今天能帮你什么？",
                },
            ];
            const [hints, setHints] = useState([]);
            const onHintClick = useCallback((content) => {
                setHints([]);
                setMessage((message) => {
                    return [
                        ...message,
                        {
                            role: 'assistant',
                            status: 'loading',
                            createAt: Date.now(),
                            id: getId()
                        }
                    ]
                });

                chartInfo.current.isChat = true;
                chartInfo.current.question = content;
                chartInfo.current.startTime = Date.now();

                generateMockResponse(content);
            }, [])
            const [message, setMessage] = useState(defaultMessage);
            const roleInfo = {
                user: {
                    name: 'User',
                    avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png'
                },
                assistant: {
                    name: activeAgentInfo.name || 'LinQ AI',
                    avatar: './imgs/logo.svg'
                },
                system: {
                    name: 'System',
                    avatar: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/other/logo.png'
                }
            }
            const globalController = useRef();
            const onChatsChange = useCallback((chats) => {
                setMessage(chats);
            }, []);

            const generateMockResponse = useCallback((content) => {
                const msgBody = {
                    agent_id: activeAgentInfo.id,
                    messages: [{
                        role: "user",
                        timestamp: Date.now(),
                        content: content
                    }]
                }
                const controller = new AbortController();
                const signal = controller.signal;
                globalController.current = controller;
                requestChart(apiChat, msgBody, signal, async (resData) => {
                    const { status, reader, error } = resData;
                    if (status !== 200) {
                        setMessage((message) => {
                            return [
                                ...message,
                                {
                                    role: 'assistant',
                                    id: 'error',
                                    content: '服务繁忙，暂时不可用',
                                    status: 'error'
                                }
                            ]
                        });
                        return;
                    } else if (status === 200) {
                        const decoder = new TextDecoder();
                        let buffer = '';
                        let lineNumber = 0, renderNumber = 0, tokenNumber = 0, finalContent = "";

                        while (true) {
                            const { done, value } = await reader.read();
                            console.log("reader2", done, value);
                            if (done) {
                                break;
                            }
                            buffer += decoder.decode(value);
                            const messages = buffer.split('\n\n');
                            buffer = messages.pop(); // 不能删除，否则会有重复数据

                            for (const message of messages) {
                                await new Promise(resolve => setTimeout(resolve, 10));

                                if (message.startsWith('data:')) {
                                    const data = message.slice(5).trim();
                                    try {
                                        const dataContent = JSON.parse(data);
                                        if (!dataContent || typeof dataContent.content !== 'string') {
                                            console.warn('Invalid data content format:', dataContent);
                                            continue;
                                        }

                                        let chunk = dataContent.content;
                                        if (chunk.includes("\n")) {
                                            chunk = chunk.replace(/\n+/g, '\n');
                                        }

                                        finalContent += chunk;
                                        chartInfo.current.tokenNumber++;
                                        chartInfo.current.finalContent = finalContent;

                                        console.log('finalContent:', finalContent);
                                        setMessage((message) => {
                                            const lastMessage = message[message.length - 1];
                                            let newMessage = { ...lastMessage };
                                            if (lastMessage.status === 'loading') {
                                                newMessage = {
                                                    ...newMessage,
                                                    content: `mock Response for ${content} \n`,
                                                    status: 'incomplete'
                                                }
                                            } else if (lastMessage.status === 'incomplete') {
                                                if (chunk === "[DONE]") {
                                                    newMessage = {
                                                        ...newMessage,
                                                        status: 'complete',
                                                        content: `${finalContent}`
                                                    }
                                                    // resetChartInfo();
                                                } else {
                                                    newMessage = {
                                                        ...newMessage,
                                                        content: `${finalContent}`
                                                    }
                                                }
                                            }
                                            return [...message.slice(0, -1), newMessage]
                                        });


                                    } catch (error) {
                                        console.error('Failed to parse SSE data:', data, error);
                                        continue;
                                    }
                                }
                                console.log(messages);
                            }
                        }
                    }
                })
            }, []);

            const onMessageSend = useCallback(async (content, attachment) => {
                setMessage((message) => {
                    return [
                        ...message,
                        {
                            role: 'assistant',
                            status: 'loading',
                            createAt: Date.now(),
                            id: getId()
                        }
                    ]
                });

                chartInfo.current.isChat = true;
                chartInfo.current.question = content;
                chartInfo.current.startTime = Date.now();

                generateMockResponse(content);
            }, []);
            const onMessageReset = useCallback((e) => {
                // setMessage((message) => {
                //     return [
                //         ...message,
                //         {
                //             role: 'assistant',
                //             status: 'loading',
                //             createAt: Date.now(),
                //             id: getId()
                //         }
                //     ]
                // });

                chartInfo.current.isChat = true;
                chartInfo.current.startTime = Date.now();

                generateMockResponse(chartInfo.current.question);
            })
            const uploadTipProps = { content: '自定义上传按钮提示信息' }
            const chartInfo = useRef({ question: '', finalContent: '', userChatId: 0, startTime: 0, tokenNumber: 0, isChat: false });
            const resetChartInfo = () => {
                chartInfo.current.question = '';
                chartInfo.current.finalContent = '';
                chartInfo.current.userChatId = 0;
                chartInfo.current.startTime = 0;
                chartInfo.current.tokenNumber = 0;
                chartInfo.current.isChat = false;
            };
            const onStopGenerator = useCallback((message) => {
                if (chartInfo.current.isChat) {
                    globalController.current.abort(); // 终止请求
                    const endTime = Date.now();
                    const spendTime = endTime - chartInfo.current.startTime
                    const obj = {
                        question: chartInfo.current.question,
                        answer: chartInfo.current.finalContent,
                        agent_id: activeAgentInfo.id,
                        end_type: 2,
                        token: chartInfo.current.tokenNumber,
                        time_consume: spendTime,
                        parent_id: chartInfo.current.userChatId
                    }
                    requestPost(apiChatCallback, obj).then(function (result) {
                        if (result.code === 0) {
                            // resetChartInfo();
                            chartInfo.current.userChatId = result.data.id;
                            setMessage((message) => {
                                const lastMessage = message[message.length - 1];
                                if (lastMessage.status && lastMessage.status !== 'complete') {
                                    const lastMessage = message[message.length - 1];
                                    let newMessage = { ...lastMessage };
                                    newMessage.status = 'complete';
                                    return [
                                        ...message.slice(0, -1),
                                        newMessage
                                    ]
                                } else {
                                    return message;
                                }
                            })
                        }
                    })
                }
            }, [chartInfo]);

            const getQuestionList = (categoryId = 1) => {
                const newUrl = apiQuestionList + "&category_id=" + categoryId;
                requestGet(newUrl)
                    .then(function (result) {
                        setHints((result.data.list || []).map((item) => (item.question + (item.prompt ? '(' + item.prompt + ')' : ''))));
                    })
                    .catch(error => {
                        console.error('获取问题列表失败:', error);
                        Toast.error('获取问题列表失败，请稍后重试');
                    });
            };

            useEffect(() => {
                getQuestionList();
            }, []);

            // 使用 useEffect 控制副作用调用
            useEffect(() => {
                if (agentList.length > 0) {
                    const index = agentList.length - 1;
                    setActiveAgentInfo({
                        id: agentList[index].id,
                        name: agentList[index].name
                    });
                }
            }, [agentList]);

            return (
                <Chat
                    className="chatDom"
                    key={align + mode}
                    align={align}
                    mode={mode}
                    chats={message}
                    roleConfig={roleInfo}
                    hints={hints}
                    onHintClick={onHintClick}
                    onChatsChange={onChatsChange}
                    onMessageSend={onMessageSend}
                    onMessageReset={onMessageReset}
                    uploadTipProps={uploadTipProps}
                    showStopGenerate={true}
                    onStopGenerator={onStopGenerator}
                    bottomSlot={
                        <div className="bottomSlot">
                            <Select
                                value={activeAgentInfo.id}
                                onChange={handleOfAgentChange}
                                style={{ width: 150 }}>
                                {
                                    agentList.map((item) => {
                                        return <Select.Option key={item.id} value={item.id}>{item.name}</Select.Option>
                                    })
                                }
                            </Select>
                        </div>
                    }
                />
            );
        }

        const TabsDom = () => {
            const [agentList, setAgentList] = useState([]);
            const [feedBackList, setFeedBackList] = useState([]);
            const [feedBackSystemList, setFeedBackSystemList] = useState([]);
            const formRef = useRef(); // 新增 ref
            // 使用 useEffect 控制副作用调用
            useEffect(() => {
                const getAgentList = () => {
                    requestGet(apiAgent)
                        .then(function (result) {
                            console.log(result.data);
                            setAgentList(result.data.list || []);
                        })
                        .catch((error) => {
                            Toast.error('获取 Agent 列表失败，请稍后重试');
                            console.error('Error fetching agent list:', error);
                        });
                }
                getAgentList();

                const getFeedbackList = () => {
                    requestGet(apiFeedbackQuestionList).then(function (result) {
                        setFeedBackList(result.data.data || []);
                    })
                }
                getFeedbackList();

                const getFeedbackSystemList = () => {
                    requestGet(apiFeedbackSystemList).then(function (result) {
                        setFeedBackSystemList(result.data || []);
                    })
                }
                getFeedbackSystemList();

            }, []);

            const handleSubmit = (values) => {
                console.log(values);
                requestPost(apiFeedbackSubmit, values).then(function (result) {
                    if (result.code === 0) {
                        Toast.info('提交成功');

                        // 清空表单
                        if (formRef.current && formRef.current.formApi.reset) {
                            formRef.current.formApi.reset();
                        }

                        requestPost(apiFeedbackPoint, { user_id: userInfo.userId }).then(function (result) {
                            if (result.code === 0) {
                                console.log("增加积分成功", userInfo.userId)
                            }
                        })
                    } else {
                        Toast.error('提交失败');
                    }
                })
            };

            return (
                <Tabs className="tabsDom" defaultActiveKey="1" tabPosition="left" type="button">
                    <TabPane
                        tab={
                            <Tooltip position="left" content="聊天" trigger="hover">
                                <svg data-type="index" className="icon" xmlns="http://www.w3.org/2000/svg" width="1em"
                                    height="1em" viewBox="0 0 24 24">
                                    <path fill="#686A82"
                                        d="M6.5 13.5h7v-1h-7zm0-3h11v-1h-11zm0-3h11v-1h-11zM3 20.077V4.616q0-.691.463-1.153T4.615 3h14.77q.69 0 1.152.463T21 4.616v10.769q0 .69-.463 1.153T19.385 17H6.077zM5.65 16h13.735q.23 0 .423-.192t.192-.423V4.615q0-.23-.192-.423T19.385 4H4.615q-.23 0-.423.192T4 4.615v13.03zM4 16V4z" />
                                </svg>
                            </Tooltip>
                        }
                        key="1"
                        itemKey="1">
                        <ChartDom agentList={agentList} />
                    </TabPane>
                    <TabPane
                        tab={
                            <Tooltip position="left" content="AI" trigger="hover">
                                <svg data-type="agent" className="icon" xmlns="http://www.w3.org/2000/svg" width="1em"
                                    height="1em" viewBox="0 0 24 24">
                                    <g fill="none" stroke="#686A82" strokeLinecap="round" strokeLinejoin="round"
                                        strokeWidth="1.5" color="currentColor">
                                        <path
                                            d="M20.5 16.929V10c0-3.771 0-5.657-1.172-6.828S16.271 2 12.5 2h-1C7.729 2 5.843 2 4.672 3.172S3.5 6.229 3.5 10v9.5" />
                                        <path d="M20.5 17H6a2.5 2.5 0 0 0 0 5h14.5" />
                                        <path
                                            d="M20.5 22a2.5 2.5 0 0 1 0-5m-8.192-5l-1.461-4.521A.72.72 0 0 0 10.154 7a.72.72 0 0 0-.693.479L8 12m7-5v5m-6.462-1.5h3.231" />
                                    </g>
                                </svg>
                            </Tooltip>
                        }
                        key="2"
                        itemKey="2">
                        <div className="agentDom">
                            <h2>Agent</h2>
                            {
                                agentList.map((item) => {
                                    return <Card key={item.id} title={item.name} style={{ marginTop: '15px' }}>
                                        {item.description}
                                    </Card>
                                })
                            }
                        </div>
                    </TabPane>
                    <TabPane
                        tab={
                            <Tooltip position="left" content="反馈" trigger="hover">
                                <svg data-type="feedback" className="icon" xmlns="http://www.w3.org/2000/svg" width="1em"
                                    height="1em" viewBox="0 0 24 24">
                                    <path fill="none" stroke="#686A82" strokeLinecap="round" strokeLinejoin="round"
                                        strokeWidth="1.5"
                                        d="m2.357 7.714l6.98 4.654c.963.641 1.444.962 1.964 1.087c.46.11.939.11 1.398 0c.52-.125 1.001-.446 1.964-1.087l6.98-4.654M7.157 19.5h9.686c1.68 0 2.52 0 3.162-.327a3 3 0 0 0 1.31-1.311c.328-.642.328-1.482.328-3.162V9.3c0-1.68 0-2.52-.327-3.162a3 3 0 0 0-1.311-1.311c-.642-.327-1.482-.327-3.162-.327H7.157c-1.68 0-2.52 0-3.162.327a3 3 0 0 0-1.31 1.311c-.328.642-.328 1.482-.328 3.162v5.4c0 1.68 0 2.52.327 3.162a3 3 0 0 0 1.311 1.311c.642.327 1.482.327 3.162.327" />
                                </svg>
                            </Tooltip>
                        }
                        key="3"
                        itemKey="3">
                        <div className="feedbackDom">
                            <Form
                                ref={formRef}
                                onSubmit={values => handleSubmit(values)}
                            >
                                <Form.Section text={'基本信息'}>
                                    <Form.Select
                                        rules={[{ required: true, message: '请选择问题类型' }]}
                                        field="feedback_question_id"
                                        label='问题类型'
                                        placeholder='请选择问题类型'
                                        style={{ width: '100%' }}
                                    >
                                        {
                                            feedBackList.map((item) => {
                                                return <Form.Select.Option key={item.id} value={item.id}>{item.name}</Form.Select.Option>
                                            })
                                        }
                                    </Form.Select>
                                    <Form.Select
                                        rules={[{ required: true, message: '请选择系统类型' }]}
                                        field="system"
                                        label='系统类型'
                                        placeholder='请选择系统类型'
                                        style={{ width: '100%' }}
                                    >
                                        {
                                            feedBackSystemList.map((item) => {
                                                return <Form.Select.Option key={item.id} value={item.id}>{item.name}</Form.Select.Option>
                                            })
                                        }
                                    </Form.Select>
                                    <Form.Input
                                        rules={[{ required: true, message: '请输入你遇到了什么问题？' }]}
                                        field="description"
                                        label='问题概要'
                                        placeholder='你遇到了什么问题？'
                                        style={{ width: '100%' }}
                                    />
                                    <Form.TextArea
                                        rules={[{ required: true, message: '请输入详细信息' }]}
                                        field="content"
                                        label='详细信息'
                                        placeholder='请详细描述出了什么问题、您采取了什么操作以及您收到了什么报错信息。'
                                        style={{ width: '100%' }}
                                        autosize={{
                                            minRows: 3,
                                            maxRows: 6
                                        }} />
                                </Form.Section>
                                <Space>
                                    <Button type="primary" htmlType="submit" className="btn-margin-right">提交(submit)</Button>
                                    <Button htmlType="reset">重置(reset)</Button>
                                </Space>
                            </Form>
                        </div>
                    </TabPane>
                </Tabs>
            );
        };

        const App = () => {
            return (
                <div className="containerWrap">
                    <TabsDom />
                </div>
            );
        }

        ReactDOM.render(
            <App />,
            document.getElementById('root')
        );
    </script>
</body>

</html>